<template>
  <div class="app-container">
    <el-row >
      <el-col :span="24">
        <el-button class="margin-right" type="text" icon="el-icon-refresh" @click="loadGroupAndRepos"/>

        <el-select style="width: 250px" size="small" v-bind:value="repositoryChoseShow" @change="loadBranchs">
          <el-option-group v-for="item in groupAndRepos"
                           :key="item.group"
                           :label="item.group">
            <el-option
              v-for="repository in item.repositorys"
              :key="repository"
              :label="repository"
              :value="{repository: repository,group: item.group}" />
          </el-option-group>
        </el-select>

        <el-button size="small" @click="addUrlDialog.show = true">新建仓库</el-button>

        <el-tag type="info" class="margin-left margin-right"><b>当前分支: </b><span>{{currentBranchName}}</span></el-tag>
        <el-button size="small" class="margin-right" icon="el-icon-download" @click="pull">pull</el-button>

        <el-select filterable style="width: 250px" size="small" v-model="currentBranchName" @change="switchBranch">
          <el-option v-for="branch in branchs" :label="branch.branchName" :value="branch.branchName" />
        </el-select>

        <el-checkbox class="margin-left " v-model="lock.force" :disabled="!lock.state">强制</el-checkbox>
        <el-button type="primary" class="margin-left" size="small" @click="lockRepository">{{lock.title}}</el-button>
      </el-col>
    </el-row>

    <el-row>
      <el-col :span="15">
        <p>说明: 创建的补丁包时,当有多个提交记录被选择的时候,只会取第一个和最后一个提交记录比较差异</p>
        <el-button type="primary" class="margin-bottom"  size="small" @click="createPatch" :disabled="!input.group || !input.repository || experimental">创建补丁</el-button>
        <el-checkbox v-model="experimental" class="margin-left margin-right">允许实验功能</el-checkbox>
        <el-button  title="实验功能,不一定能保证正确性" type="primary" class="margin-bottom margin-left" size="small" @click="createPatchMultiCommit" :disabled="!input.group || !input.repository || !experimental">创建多提交记录补丁</el-button>

        <el-table
          :data="commits"
          border
          stripe
          ref="commitTable"
          v-loading="tableLoad"
          height="500"
          row-key="commitId"
          size="mini">
          <el-table-column
            type="index"
            width="50"/>
          <el-table-column
            :selectable="checkSelect"
            type="selection"
            width="55"/>
          <el-table-column
            prop="author"
            label="作者"
            width="180"/>
          <el-table-column
            prop="message"
            label="提交信息"/>
          <el-table-column
            prop="time"
            label="提交时间"
            width="150"/>
          <el-table-column
            fixed="right"
            label="操作"
            width="100">
            <template slot-scope="scope">
              <el-button type="text" size="small" :disabled="scope.row.commitId === commits[0].commitId" @click="switchBranch(scope.row.commitId)">切换</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-col>
      <el-col :span="9">
        <el-tree
          v-loading="moduleTree.loading"
          :props="moduleTree.treeProps"
          :data="moduleTree.data"
          :default-expand-all="true"
          :highlight-current="true"
        >
          <div :title="data.relativePath" class="custom-tree-node" slot-scope="{ node, data }">
            <b>{{data.moduleName}}</b>
            <span class="margin-left">{{data.lastCompileTime || '未编译'}}</span>
            <el-button type="text" size="mini" @click="compile(data.relativePath)">编译</el-button>
          </div>
        </el-tree>
<!--        <el-table-->
<!--          :data="pomFiles"-->
<!--          border-->
<!--          stripe-->
<!--          ref="pomTable"-->
<!--          v-loading="compileLoad"-->
<!--          height="500"-->
<!--          size="mini">-->
<!--          <el-table-column-->
<!--            type="index"-->
<!--            width="50"/>-->
<!--          <el-table-column-->
<!--            prop="moduleName"-->
<!--            label="模块名"-->
<!--            width="180"/>-->
<!--          <el-table-column-->
<!--            prop="relativePath"-->
<!--            label="路径"/>-->
<!--          <el-table-column-->
<!--            fixed="right"-->
<!--            label="操作"-->
<!--            width="100">-->
<!--            <template slot-scope="scope">-->
<!--              <el-button type="text" size="small" @click="compile(scope.row)">编译</el-button>-->
<!--            </template>-->
<!--          </el-table-column>-->
<!--        </el-table>-->
      </el-col>
    </el-row>

    <!-- 编译结果 -->
    <el-dialog  fullscreen :visible.sync="compileResultDialog.show" @close="closeDialog" title="编译结果">
      <pre ref="output" style="overflow-y: scroll;height: 87vh">{{compileResultDialog.message}}</pre>
    </el-dialog>

    <!-- 添加仓库 -->
    <el-dialog :visible.sync="addUrlDialog.show" v-loading="addUrlDialog.loading" title="添加克隆">
      <el-form size="small">
        <el-form-item label="分组">
          <el-select v-model="addUrlDialog.input.group" >
            <el-option v-for="group in addUrlDialog.groups" :label="group" :value="group" />
          </el-select>
        </el-form-item>
        <el-form-item label="地址">
          <el-input placeholder="输入仓库地址" v-model="addUrlDialog.input.url" />
        </el-form-item>

        <el-button size="small" type="primary" @click="cloneRepository">添加</el-button>
      </el-form>
    </el-dialog>

    <!-- 编译文件预览 -->
    <el-dialog :title="changeFilesDialog.title" :visible.sync="changeFilesDialog.show">
      <div class="margin-bottom" style="margin-top:  -10px">
        源文件数量 <b>{{compileCount.originFiles}}</b> -> 编译后文件数量 <b>{{compileCount.compileFiles}}</b>
        <span v-if="compileCount.errorFiles" class="margin-left text-danger" style="color: red">错误文件数量: {{compileCount.errorFiles}}</span>
      </div>
      <el-table
        :data="changeFilesDialog.data != null ? changeFilesDialog.data.changeFiles : []"
        border
        stripe
        height="500"
        size="mini">
          <el-table-column type="expand">
            <template slot-scope="props">
              <div class="margin-small-bottom" v-for="path in props.row.compileFiles">
                <span class="margin-right">{{path.path}}</span>
                <span >{{formatTime(path.time)}}</span>
              </div>
            </template>
          </el-table-column>
        <el-table-column
          type="index"
          label="序号" width="55"/>
          <el-table-column
            prop="changeType"
            label="变更类型" width="100"/>
          <el-table-column
            prop="relativePath"
            label="路径"/>
          <el-table-column
            label="编译文件数量" width="100">
            <template slot-scope="scope">
              <span v-if="scope.row.compilePaths.length === 0 && scope.row.changeType !== 'DELETE'" class="text-danger" style="color: red">{{scope.row.compilePaths.length}}</span>
              <span v-else class="">{{scope.row.compilePaths.length}}</span>
            </template>
          </el-table-column>
      </el-table>

      <el-button class="margin-top" type="primary" size="small" @click="downloadPatch">下载补丁</el-button>
    </el-dialog>
  </div>
</template>

<script>
import git from "@/api/git";
import core from "@/api/core";

import {formatTime} from "@/utils";

export default {
  name: "git",
  data(){
    return {
      lock:{
        state: true,
        title: '解锁',
        force: false
      },
      groupAndRepos:[],
      currentBranchName: null,
      branchs: [],
      commits: [],
      tableLoad: false,
      compileLoad: false,
      pomFiles: [],
      experimental: true,
      input: {
        group: null,
        repository: null,
        commitBeforeId: null,
        commitAfterId: null,
        commitIds: []
      },
      switchBranchInput: {
        branchName: null
      },
      compileResultDialog: {
        show : false,
        message: '',
        websocket: null
      },
      addUrlDialog:{
        loading: false,
        show: false,
        groups: [],
        input: {
          group: null,
          url: null
        }
      },
      changeFilesDialog:{
        show: false,
        data: null,
        title: '变更文件列表',
        patchMethod: null
      },
      moduleTree:{
        loading: false,
        treeProps:{
          children: 'childrens',
          label: 'moduleName'
        },
        data: []
      }
    }
  },
  methods:{
    formatTime,
    lockRepository(){
      if (this.lock.state){
        git.unLock(this.input.group,this.input.repository,this.lock.force).then(res => {
          this.lock.state = false;
          this.lock.title = '锁定'
        })
      }else{
        git.lock(this.input.group,this.input.repository).then(res => {
          this.lock.state = true;
          this.lock.title = '解锁';
        })
      }
    },
    checkSelect(row,index){
      if (this.experimental){
        return true;
      }
      return index !== 0;
    },
    cloneRepository(){
      this.addUrlDialog.loading = true;
      git.cloneRepository(this.addUrlDialog.input.group,this.addUrlDialog.input.url).then(res => {
        this.addUrlDialog.show = false;
        this.loadGroupAndRepos();
        this.addUrlDialog.loading = false;
      }).catch(res => {
        this.addUrlDialog.loading = false;
      })
    },
    loadGroupAndRepos(){
      git.groupRepositorys().then(res => {
        this.groupAndRepos = res.data;

        if (this.groupAndRepos.length > 0){
          // 默认选择第一个分组和仓库
          this.loadBranchs({group: this.groupAndRepos[0].group,repository: this.groupAndRepos[0].repositorys[0]});
        }

      })
    },
    loadBranchs(value){
      this.input.group = value.group;
      this.input.repository = value.repository;

      git.branchs(this.input.group,this.input.repository).then(res => {
        this.branchs = res.data.branches;
        this.currentBranchName = res.data.currentBranchName;

        this.loadCommits();
        this.loadPomFiles();
      })
    },
    loadCommits(){
      this.tableLoad = true;
      git.commits(this.input.group,this.input.repository).then(res => {
        this.tableLoad = false;
        this.commits = res.data;
        if (this.commits && this.commits.length > 0 && !this.experimental){
          // 默认选中第一行
          this.$nextTick(function() {
            this.$refs['commitTable'].toggleRowSelection(this.commits[0]);
          });
        }
      }).catch(res => {
        this.tableLoad = false;
      })
    },
    loadPomFiles(){
      // git.pomFiles(this.input.group,this.input.repository).then(res => {
      //   this.pomFiles = res.data;
      // })
      // 改为加载模块树
      this.moduleTree.loading = true;
      git.modules(this.input.group,this.input.repository).then(res => {
        this.moduleTree.data = res.data;
        this.moduleTree.loading = false;
      }).catch(res => {
        this.moduleTree.loading = false;
      })
    },
    compile(relativePath){
      git.lock(this.input.group,this.input.repository).then(res => {
        this.compileResultDialog.message = '';

        let websocketId = Math.round(Math.random() * 1000);
        let wsAddr = process.env.VUE_APP_BASE_API.replace('http','ws');
        console.log(wsAddr,'wsAddr');
        if (wsAddr === '/'){
          wsAddr = 'ws://'+window.location.host+'/'
        }
        this.compileResultDialog.websocket = new WebSocket(wsAddr + '/compile/message/'+websocketId);
        let _this = this;
        this.compileResultDialog.websocket.onopen = function (){
          _this.compileResultDialog.websocket.send(JSON.stringify({websocketId:websocketId,group:_this.input.group,repository:_this.input.repository,relativePath:relativePath}));
        }

        this.compileResultDialog.websocket.onmessage = this.reviceMessage;
        this.compileResultDialog.show = true;
      })

      // git.compile(websocketId,this.input.group,this.input.repository,relativePath).then(res => {});
    },
    closeDialog(){
      if (this.compileResultDialog.websocket){
        this.compileResultDialog.websocket.close();
      }

    },
    reviceMessage(event){
      let data = event.data;
      this.compileResultDialog.message += data;
      this.compileResultDialog.message += '\n';
      this.$refs.output.scrollTop = this.$refs.output.scrollHeight
    },
    switchBranch(branchName){
      git.lock(this.input.group,this.input.repository).then(res => {
        this.tableLoad = true;
        git.switchBranch(this.input.group,this.input.repository,branchName).then(res => {
          this.tableLoad = false;
          this.loadCommits();
          this.loadPomFiles();
        }).catch(res => {
          this.tableLoad = false;
        })
      })
    },
    pull(){
      this.tableLoad = true;
      git.pull(this.input.group,this.input.repository).then(res => {
        this.tableLoad = false;
        this.loadBranchs({group: this.input.group,repository: this.input.repository})
      })
    },
    downloadPatch(){
      this.changeFilesDialog.patchMethod.call(this,this.input).then(res => {
        core.fileDownload(res.data);
      })
    },
    createPatch(){
      let select = this.$refs['commitTable'].selection;
      if (!select || select.length < 2){
        this.$message('第一个提交必须选中,然后还必须再选一个做对比');
        return ;
      }

      git.newCompileTime(this.input.group,this.input.repository).then(res => {
        if (res.data < new Date().getTime() - 3600000){
          // 如果超过一小时没编译 , 提示用户编译
          this.$confirm('超过一小时('+formatTime(res.data)+')没有编译项目了,确定要创建补丁吗','警告',{type: 'warning'}).then(() => {
            this.doCreatePatch(select);
          }).catch(()=>{})
        }else{
          this.doCreatePatch(select);
        }
      })

    },
    doCreatePatch(select){
      this.input.commitBeforeId = select[select.length - 1]['commitId'];
      this.input.commitAfterId = select[0]['commitId'];
      git.changeFiles(this.input).then(res => {
        this.changeFilesDialog.data = res.data;
        this.changeFilesDialog.title = this.input.commitBeforeId+" compare " + this.input.commitAfterId;
        this.changeFilesDialog.show = true;
        this.changeFilesDialog.patchMethod = git.createPatch;
      })
    },
    createPatchMultiCommit(){
      let select = this.$refs['commitTable'].selection;
      if (!select || select.length < 1){
        this.$message('必须选中至少一个提交记录');
        return ;
      }

      git.newCompileTime(this.input.group,this.input.repository).then(res => {
          if (res.data < new Date().getTime() - 3600000){
            this.$confirm('超过一小时('+formatTime(res.data)+')没有编译项目了,确定要创建补丁吗','警告',{type: 'warning'}).then(() => {
             this.doCreatePatchMultiCommit(select);
            }).catch(()=>{})
          }else{
            this.doCreatePatchMultiCommit(select);
          }
      })

    },
    doCreatePatchMultiCommit(select){
      this.input.commitIds = [];
      for (let i = 0; i < select.length; i++) {
        this.input.commitIds.push(select[i].commitId);
      }
      git.changeFilesV2(this.input).then(res => {
        this.changeFilesDialog.data = res.data;
        this.changeFilesDialog.title = this.input.commitIds.length+' 个提交记录的差异';
        this.changeFilesDialog.show = true;
        this.changeFilesDialog.patchMethod = git.createPatchV2;
      })
    }
  },
  mounted() {
    this.loadGroupAndRepos();
    git.groups().then(res => {
      this.addUrlDialog.groups = res.data;
    })
  },
  computed:{
    repositoryChoseShow(){
      return this.input.group+"->"+this.input.repository;
    },
    compileCount(){
      if (this.changeFilesDialog.data && this.changeFilesDialog.data.changeFiles){
        let originFiles = this.changeFilesDialog.data.changeFiles.length;
        let compileFiles = 0 ,errorFiles = 0;
        for (let i = 0; i < this.changeFilesDialog.data.changeFiles.length; i++) {
          let changeFile = this.changeFilesDialog.data.changeFiles[i];
          compileFiles += changeFile.compilePaths.length;

          if (changeFile.compilePaths.length === 0 && changeFile.changeType !== 'DELETE'){
            errorFiles ++;
          }
        }

        return {originFiles,compileFiles,errorFiles};
      }
      return {originFiles:0,compileFiles:0,errorFiles: 0};
    }
  }
}
</script>

<style scoped>
  /deep/ .custom-tree-node{
    display: flex !important;
    justify-content: space-between;
    align-items: center;
    display: block;
    width: 100%;
    padding: 0 10px 0 2px;
  }
</style>
